package com.tbit.common.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tbit.common.config.TbitProperties;
import com.tbit.common.entity.openapi.MobileNameAuthResult;
import lombok.extern.slf4j.Slf4j;

import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

/**
 * @Author: chen
 * @Description:
 * @Date: 创建于 11:32 2023/8/14
 */
@Slf4j
public class TbitHttpServiceUtil {


    public static final String TIMESTAMP_KEY = "timestamp";

    public static final String APP_ID_KEY = "appId";

    public static final String NONCE_KEY = "nonce";

    private static final String HEX_DIGITS[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
    //licensePhoto
    public static final Integer LICENSE_PHOTO_RETURN_BIKE_SUCCESS = 1;

    public static final Integer LICENSE_PHOTO_RETURN_BIKE_FAIL = 0;

    //车牌拍照贵阳模型
    public static final String LICENSE_MODEL_GUI_YANG = "GUI_YANG";
    //车牌拍照安益模型
    public static final String LICENSE_MODEL_AN_YI = "AN_YI";

    public static String getSign(String timestamp, String appId, String nonce, String appSecret, Map<String, Object> param) {
        Map<String, Object> map = new HashMap<>();
        map.putAll(param);
        map.put(TIMESTAMP_KEY, timestamp);
        map.put(NONCE_KEY, nonce);
        map.put(APP_ID_KEY, appId);

        Map<String, Object> sortMap = new TreeMap<>(String::compareTo);
        sortMap.putAll(map);

        StringBuilder strBuilder = new StringBuilder();
        boolean isFirst = true;
        for (Map.Entry<String, Object> entry : sortMap.entrySet()) {
            if (entry.getKey() != null && entry.getValue() != null) {
                if (isFirst) {
                    isFirst = false;
                } else {
                    strBuilder.append("&");
                }
                strBuilder.append(entry.getKey()).append("=").append(entry.getValue().toString());
            }
        }
        strBuilder.append(appSecret);
        return md5(strBuilder.toString()).toUpperCase();
    }


    private static String md5(String origin) {
        String resultString = null;
        String charsetname = "UTF-8";
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname)) {
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            } else {
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes(charsetname)));
            }
        } catch (Exception exception) {
        }
        return resultString;
    }

    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            resultSb.append(byteToHexString(b[i]));
        }

        return resultSb.toString();
    }


    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n += 256;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return HEX_DIGITS[d1] + HEX_DIGITS[d2];
    }

    private static String doJsonPost(String urlPath, Map<String, String> headers, String body) {
        Long t = System.currentTimeMillis();
        System.out.println("请求时间：" + DateUtil.date());
        HttpRequest request = HttpUtil.createPost(urlPath).timeout(10000);
        headers.forEach(request::header);
        request.body(body);
        String result = request.execute().body();
        System.out.println("响应时间：" + DateUtil.date());
        log.info("{},tbit接口调用耗时{}毫秒", urlPath, System.currentTimeMillis() - t);
        return result;
    }

    /**
     * 数据构造
     *
     * @param appId     appId
     * @param nonce     nonce
     * @param appSecret appSecret
     * @param param     附加参数
     * @param headers   请求头
     * @return
     */
    public static String getJson(String appId, String nonce, String appSecret, Map<String, Object> param, Map<String, String> headers) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String signStr = getSign(timestamp, appId, nonce, appSecret, param);
        headers.put("appId", appId);
        headers.put("nonce", nonce);
        headers.put("timestamp", timestamp);
        headers.put("sign", signStr);
        String json = JSON.toJSONString(param);
        return json;
    }

    /**
     * 图片人脸对比认证
     *
     * @param appId     appId
     * @param nonce     nonce
     * @param appSecret appSecret
     * @param imageA    图片A oss地址
     * @param imageB    图片B oss地址
     */
    public static Boolean faceCompare(String appId, String nonce, String appSecret, String imageA, String imageB, Integer face_sm) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("imageA", imageA);
            param.put("imageB", imageB);
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, param, headers);
            String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/faceCompare", headers, json);
            log.info("图片人脸对比认证={}", resp);
            JSONObject jsonObject = JSON.parseObject(resp);
            if ("200".equalsIgnoreCase(jsonObject.getString("code")) && jsonObject.getJSONObject("data").getDouble("similarity") * 100 >= face_sm) {
                return true;
            }
        } catch (Exception e) {
            log.error("youqu图片人脸对比认证异常", e);
        }
        return false;
    }

    /**
     * 身份证号和人脸认证
     *
     * @param appId     appId
     * @param nonce     nonce
     * @param appSecret appSecret
     * @param image     图片oss地址
     * @param name      名称
     * @param idNO      身份证号码
     */
    public static Boolean idfaceIdentity(String appId, String nonce, String appSecret, String image, String name, String idNO) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("image", image);
            param.put("name", name);
            param.put("idNO", idNO);
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, param, headers);
            String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/idfaceIdentity", headers, json);
            log.info("身份证号和人脸认证结果={}", resp);
            JSONObject jsonObject = JSON.parseObject(resp);
            if ("200".equalsIgnoreCase(jsonObject.getString("code")) && jsonObject.getJSONObject("data").getBoolean("result")) {
                return true;
            }
        } catch (Exception e) {
            log.error("youqu身份证号和人脸认证异常", e);
        }
        return false;
    }

    /**
     * 实名认证
     *
     * @param appId     appId
     * @param nonce     nonce
     * @param appSecret appSecret
     * @param name      名称
     * @param idNO      身份证号码
     */
    public static Boolean nameAuth(String appId, String nonce, String appSecret, String name, String idNO) {

        try {
            Map<String, Object> param = new HashMap<>();
            param.put("idNO", idNO);
            Map<String, String> headers = new HashMap<>();
            param.put("name", name);
            String json = getJson(appId, nonce, appSecret, param, headers);
            String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/nameAuth", headers, json);
            log.info("实名认证结果={}", resp);
            JSONObject jsonObject = JSON.parseObject(resp);
            if ("200".equalsIgnoreCase(jsonObject.getString("code")) && jsonObject.getJSONObject("data").getBoolean("result")) {
                return true;
            }
        } catch (Exception e) {
            log.error("youqu实名认证异常", e);
        }
        return false;
    }

    /**
     * 活体检测
     *
     * @param appId     appId
     * @param nonce     nonce
     * @param appSecret appSecret
     * @param image     图片oss地址
     */
    public static boolean liveDetect(String appId, String nonce, String appSecret, String image) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("image", image);
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, param, headers);
            String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/liveDetect", headers, json);
            log.info("活体检测结果={}", resp);
            JSONObject jsonObject = JSON.parseObject(resp);
            if ("200".equalsIgnoreCase(jsonObject.getString("code")) && jsonObject.getJSONObject("data").getBoolean("alive")) {
                return true;
            }
        } catch (Exception e) {
            log.error("youqu活体检测异常", e);
        }

        return false;
    }

    /**
     * 拍照还车
     *
     * @param appId     appId
     * @param nonce     nonce
     * @param appSecret appSecret
     * @param image     图片base64字符串
     * @return
     */
    public static String photographAngle(String appId, String nonce, String appSecret, String image, Integer photoReturnAngle
            , Integer photoReturnDistance, String bicycleSignColor) {
        return photographAngle(appId, nonce, appSecret, image, photoReturnAngle, photoReturnDistance, bicycleSignColor, null);
    }

    public static String photographAngle(String appId, String nonce, String appSecret, String image, Integer photoReturnAngle
            , Integer photoReturnDistance, String bicycleSignColor, Integer mode) {

        Map<String, Object> param = new HashMap<>(8);
        param.put("photoReturnAngle", photoReturnAngle);
        param.put("photoReturnDistance", photoReturnDistance);
        param.put("bicycleSignColor", bicycleSignColor);
        param.put("file", image);
        param.put("mode", mode);
        Map<String, String> headers = new HashMap<>(8);
        String json = getJson(appId, nonce, appSecret, param, headers);
        String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/photographAngle", headers, json);
        log.info("拍照还车结果={}", resp);
        return resp;
    }

    /**
     * 人脸识别活体+比对
     *
     * @param appId      appId
     * @param nonce      nonce
     * @param appSecret  appSecret
     * @param name       姓名
     * @param idNO       身份证号码
     * @param existImage 已存在图片oss
     * @param checkImage 待校验图片oss地址
     * @return
     */
    public static String realPerson(String appId, String nonce, String appSecret, String name, String idNO, String existImage, String checkImage) {

        try {
            Map<String, Object> param = new HashMap<>();
            param.put("idNO", idNO);
            param.put("name", name);
            param.put("existImage", existImage);
            param.put("checkImage", checkImage);
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, param, headers);
            String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/realPerson", headers, json);
            log.info("{}实人认证结果={}", idNO, resp);
            JSONObject jsonObject = JSON.parseObject(resp);
            if ("200".equalsIgnoreCase(jsonObject.getString("code"))) {
                return jsonObject.getString("data");
            }
            if ("使用次数不足".equals(jsonObject.getString("msg"))) {
                return "";
            }
        } catch (Exception e) {
            log.error("youqu实名认证异常", e);
        }
        return null;
    }


    /**
     * 发送优驱 API 短信
     *
     * @param appId      配置appid
     * @param nonce      配置随机数
     * @param appSecret  密钥
     * @param phone      手机号码
     * @param paramsJson     参数
     * @param templateId 模板id
     * @return true代表可以发送成功、false代表失败
     */
    public static boolean sendSms(String appId, String nonce, String appSecret, String phone, String paramsJson, Integer templateId) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("phone", phone);
            param.put("params", paramsJson);
            param.put("templateId", templateId);
            log.info("Tbit 发送短信：{}", param);
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, param, headers);
            // http://101.37.146.126:8013/openApi/sms/send
            String resp = doJsonPost( TbitProperties.getUrl() + "/openApi/sms/send", headers, json);
            log.info("短信发送结果={}", resp);
            JSONObject jsonObject = JSON.parseObject(resp);
            if ("200".equalsIgnoreCase(jsonObject.getString("code"))) {
                return true;
            }
        } catch (Exception e) {
            log.error("youqu短信发送异常", e);
        }
        return false;
    }

    /**
     * 发送优驱 API 短信
     *
     * @param appId      配置appid
     * @param nonce      配置随机数
     * @param appSecret  密钥
     * @param phone      手机号码
     * @param params     参数
     * @param templateId 模板id
     * @return true代表可以发送成功、false代表失败
     */
    public static boolean sendSms(String appId, String nonce, String appSecret, String phone, JSONObject params, Integer templateId) {
        return sendSms(appId, nonce, appSecret, phone, params.toJSONString(), templateId);
    }

    /**
     * 车牌拍照还车
     *
     * @param appId               配置appid
     * @param nonce               配置随机数
     * @param appSecret           密钥
     * @param image               图片base64字符串
     * @return
     */
    public static String licensePhotoReturnBike(String appId, String nonce, String appSecret, String image,String type) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("file", image);
            if(Objects.nonNull(type)){
                param.put("type", type);
            }
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, param, headers);
            String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/licensePhotoReturnBike", headers, json);
            log.info("车牌拍照还车结果={}", resp);
            return resp;
        } catch (Exception e) {
            log.error("车牌拍照还车异常", e);
        }
        return null;
    }

    /**
     * 优驱api腾讯云人脸识别
     * @param appId 配置appid
     * @param nonce 配置随机数
     * @param appSecret 密钥
     * @param redirectUrl 回调地址
     * @param oldImg base64
     * @param name 名称
     * @param idNO 身份证号码
     * @return result
     */
    public static Map<String, Object> getToken(String appId, String nonce, String appSecret, String redirectUrl, String oldImg, String name, String idNO) {
        Map<String, Object> result = new HashMap<>();
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("redirectUrl", redirectUrl);
            if (Objects.nonNull(oldImg)){
                map.put("oldImg", oldImg);
            }
            map.put("name", name);
            map.put("type", 1);
            map.put("idNO", idNO);
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, map, headers);
            String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/specialFaceCheck", headers, json);
            if (resp.contains("使用次数不足")) {
                return result;
            }
            JSONObject jsonObject = JSON.parseObject(resp);
            JSONObject data = jsonObject.getJSONObject("data");
            result.put("bizToken",data.getString("bizToken"));
            result.put("url",data.getString("url"));
            result.put("requestId",data.getString("requestId"));
            log.info("身份证号:{},优驱腾讯云人脸识别获取bizToken结果={}", idNO, data.getString("bizToken"));
            return result;
        } catch (Exception e) {
            log.error("优驱腾讯云人脸识别失败", e);
        }
        return result;
    }


    /**
     * 获取腾讯云人脸结果
     * @param appId 配置appid
     * @param nonce 配置随机数
     * @param appSecret 密钥
     * @param bizToken 人脸token
     * @return boolean
     */
    public static Map<String, Object> getResult(String appId, String nonce, String appSecret, String bizToken, String oldImg){
        long startTime = System.currentTimeMillis();
        //构建返回map
        Map<String, Object> response = new HashMap<>();
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("type", 2);
            map.put("bizToken", bizToken);
            if (Objects.nonNull(oldImg)){
                map.put("oldImg", oldImg);
            }
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, map, headers);
            long before = System.currentTimeMillis();
            log.info("调用接口前耗时:{}", before - startTime);
            String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/specialFaceCheck", headers, json);
            log.info("调用接口耗时:{}", System.currentTimeMillis() - before);
            JSONObject jsonObject = JSON.parseObject(resp);
            JSONObject data = jsonObject.getJSONObject("data");
            if (Objects.nonNull(data.getString("bestFrame"))){
                response.put("bestFrame", data.getString("bestFrame"));
            }
            if (Objects.nonNull(data.getString("sim"))){
                response.put("sim", data.getString("sim"));
            }
            response.put("result", data.getString("result"));
            log.info("bizToken:{}, 优驱腾讯云人脸识别结果:{}", bizToken, response);
            return response;
        } catch (Exception e) {
            log.error("优驱腾讯云人脸识别失败", e);
            return response;
        }
    }

  // 优驱人脸识别自研获取bizToekn结果
    public static Map<String, Object> getTokenLocal(String url, String appId, String nonce, String appSecret, String redirectUrl, String oldImg, String name, String idNO) {
        Map<String, Object> result = new HashMap<>();
        try {
            Map<String, Object> map = new HashMap<>();
//            map.put("redirectUrl", redirectUrl);
            if (Objects.nonNull(oldImg)){
                map.put("oldImg", oldImg);
            }
            map.put("name", name);
//            map.put("type", 1);
            map.put("idNO", idNO);
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, map, headers);
            String resp = doJsonPost(url + "/openApi/livingFaceAuth/getToken", headers, json);
            log.info("优驱人脸识别自研获取bizToekn结果={}", resp);
            if (resp.contains("使用次数不足")) {
                return result;
            }
            JSONObject jsonObject = JSON.parseObject(resp);
            JSONObject data = jsonObject.getJSONObject("data");
            if (data != null){
                result.put("bizToken",data.getString("bizToken"));
                result.put("url",data.getString("url"));
            }
            result.put("msg",jsonObject.getString("msg"));
//            result.put("requestId",data.getString("requestId"));
            return result;
        } catch (Exception e) {
            log.error("优驱人脸识别自研失败", e);
        }
        return result;
    }



    // 获取是否人脸识别成功
    public static Map<String, Object> getTencentResultLoacl(String url, String appId, String nonce, String appSecret, String bizToken) {
        Map<String, Object> result = new HashMap<>();
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("bizToken", bizToken);
            Map<String, String> headers = new HashMap<>();
            String json = getJson(appId, nonce, appSecret, map, headers);
            String resp = doJsonPost(url + "/openApi/livingFaceAuth/getResult", headers, json);
            log.info("优驱人脸识别自研获取人脸认证结果={}", resp);
            JSONObject jsonObject = JSON.parseObject(resp);
            JSONObject data = jsonObject.getJSONObject("data");
            result.put("result",data.getString("result"));
            result.put("sim",data.getString("sim"));
            result.put("bestFrame",data.getString("bestFrame"));
            result.put("reason",data.getString("reason"));
//            result.put("requestId",data.getString("requestId"));
            return result;
        } catch (Exception e) {
            log.error("优驱人脸识别自研获取人脸认证结果失败", e);
        }
        return result;
    }

    // 运营商三要素认证
    public static MobileNameAuthResult mobileNameAuth(String appId, String nonce, String appSecret, String phone, String name, String idNO) {
        Map<String, Object> map = new HashMap<>();
        map.put("phone", phone);
        map.put("name", name);
        map.put("idNO", idNO);

        Map<String, String> headers = new HashMap<>();
        String json = getJson(appId, nonce, appSecret, map, headers);
        String resp = doJsonPost(TbitProperties.getUrl() + "/openApi/mobileNameAuth", headers, json);
        log.info("优驱运营商三要素认证结果={}", resp);
        JSONObject jsonObject = JSON.parseObject(resp);
        MobileNameAuthResult result = jsonObject.getObject("data", MobileNameAuthResult.class);
        if (result != null) {
            return result;
        }
        return new MobileNameAuthResult("未知错误", false);
    }


    /**
     * 获取用量
     * @param appId         配置appid
     * @param nonce         配置随机数
     * @param appSecret     密钥
     * @return JSON
     */
    public static JSONObject getSurplus(String appId, String nonce, String appSecret){
        try {
            String timestamp = String.valueOf(System.currentTimeMillis());
            Map<String, String> headers = new HashMap<>();
            headers.put("appId", appId);
            headers.put("nonce", nonce);
            headers.put("timestamp", timestamp);
            headers.put("sign", getSign(timestamp, appId, nonce, appSecret, new HashMap<>()));
            String resp = doJsonPost( TbitProperties.getUrl() + "/openApi/surplus", headers, "{}");
            log.info("获取用量结果={}", resp);
            JSONObject jsonObject = JSON.parseObject(resp);
            if ("200".equalsIgnoreCase(jsonObject.getString("code"))) {
                return jsonObject;
            }
        } catch (Exception e) {
            log.error("youqu获取用量异常", e);
        }
        return null;
    }



    public static void main(String[] args) {
        String url = "http://101.37.146.126:8013";
        String appId = "pkprlwws";
        String nonce = "pkprlwws";
        String appSecret = "55f550de36d44092ae25813c6e32b38a";
        String bizToken = "7D50E7B9-ED94-4256-8DC8-D1F46CD7863F";
//        String redirectUrl = "https://clientv3.uqbike.cn/weixinPay/notify.do";
//        String oldImg = "asdjasdhdaskd";
//        String name = "张敏";
//        String idNO = "1124563";
//        Map<String, Object> token = getToken(url, appId, nonce, appSecret, redirectUrl, oldImg, name, idNO);
//        System.out.println(token);
    }
    //7D50E7B9-ED94-4256-8DC8-D1F46CD7863F

}
